package com.example.demo.controller;


import com.example.demo.entity.Userinfo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@Controller   // 让 spring 启动时，把这个路由加载到spring中
@ResponseBody  // 注意是响应体 ResponseBody。作用：表示返回的是数据，不是一个静态的页面，也就是只返回数据，前后端分离
//@RestController 这一个注释 可以代替上面两个注释
public class UserController {

    //@RequestMapping("/sayhi")      // 路由的规则注册 (也就是url 网址)，默认接收 get 和 post 请求
    @RequestMapping(value = "/sayhi",method = RequestMethod.POST)  // 表示只接收post的请求，get请求会405
    public String say() {
        return "hi spring mvc";
    }

    @PostMapping("/hello")  //注释表示只接收 post 的请求
    public String say2() {
        return "hello spring mvc";
    }

    @GetMapping("/hello2")  //注释表示只接收 get 的请求
    public String sayhi() {
        return "hello spring mvc";
    }

    /**
     * 存储会话session, 和 servlet 时是一样的
     * @return
     */
    @RequestMapping("setsession")
    public void saveSession(HttpServletRequest request) {
        //  获取 HttpSession 对象，参数设置为 true 表示如果没有 session 对象就创建⼀个session
        HttpSession session = request.getSession(false); // 不写默认是true
        if(session == null) {

            session.setAttribute("key","zhangsan");
        }
    }

    // 获取 session 会话，要先进行存储会话才可以获取
    @RequestMapping("/getsession")
    public Object getSession(@SessionAttribute("key")String session) {
        return session;
    }

    /**
     * 获取header
     * @param head
     * @return
     */
    // 7.获取参数类型：获取header
    @RequestMapping("getheader")
    public Object getHeader(@RequestHeader("User-Agent") String head) {
        return "header-> " + head;
    }

    /**
     * 获取cookie
     * @param cookie
     * @return
     */
    // 6.使用注解来获取到cookie
    @RequestMapping("getcookie")  //required = false 默认是true 表示前端必须传递 ，不传递就会400
                                  // @CookieValue(value = "java" 参数表示 筛选出名称为 java 的一条   cookie
    public Object getCookie(@CookieValue(value = "java" ,required = false) String cookie) {
        return cookie;
    }

    // 获取？后面的参数 ，也可以后端重命名,通过url中 ？ 后面的内容传递参数
    //     // 注意加上 RequestParam 的效果就是 重命名 和 设置前端是不是必须传递这个参数
    @RequestMapping("sayhi9")  // required = false 默认是true 表示前端要传递这个参数，不传递前端就会状态码 400 ，false表示不是一定要传，不传就是默认值
    public String say9(@RequestParam(value = "username" , required = true) String name,String password) {
        return "hi spring mvc name: " + name  +  " | password: " + password;
    }


    /**
     *  4. 从基础 url 中获取参数, 注解：@RequestParam
     *     需要注意 @RequestMapping 注解中参数的设置
     *     比如：url: localhost:8080/url/zhangsan/123
     *     @PathVariable 获取很多字段时， 每个参数都要添加一个 @PathVariable注解
     * @return
     */
    // 4.从基础 url 中获取参数(不是url的参数部分获取参数，而是 ？之前的参数)
    @RequestMapping("/url/{username}/{password}")
//    public Object getURL(@PathVariable(name = "username",required = false)String name, String password) {
    public Object getURL(@PathVariable(name = "username",required = false)String name,@PathVariable String password) {
        return "name: " + name + " ， password: " + password;
    }
    /**
     *  3.获取到 json 格式的对象，用到 @RequestBody 注解
     * @param userinfo
     * @return
     */
    // 3. 获取json 格式的对象
    @RequestMapping("/json")
    public Object getInfo( @RequestBody Userinfo userinfo ) {
        return userinfo;
    }


    /**
     *  2.获取对象
     * @param userinfo
     * @return
     */
    // 2. 获取对象
    @RequestMapping("sayhi8")
    public Object reg(Userinfo userinfo) {
        /**
         *
         * 注意此处的对象不是 json对象，而是在 url 里输入的参数，获取到参数，构造成Userinfo对象，赋值给userinfo
         * 注意 不能是 json 构造的，会获取不到
         */
        System.out.println(userinfo);

        /**
         * 返回的是一个 Object 对象，但是MVC框架会自动帮我们封装成一个 json 对象的
         */

        return userinfo;
    }

    // 1.2 获取多个参数
    @RequestMapping("/sayhi7")   // 传递多个参数, 不区分顺序，但是名字要对应
    public String say7(String name,String password) {
        System.out.println("获取多个参数");
        return "hi spring mvc name: " + name  +  " | password: " + password;
    }

    @RequestMapping("/sayhi6")   // SpringMVC, 就是基于 servlet 的，
                                 // 所以内置了这两个隐藏的对象，项目启动的时候，就会把对象赋值给这两个参数
    public String say6(HttpServletRequest request, HttpServletResponse response) throws IOException {

        //return "hi spring mvc " + name;
        // 重定向
        response.sendRedirect("https://baidu.com");
        return "hi spring mvc " + request.getParameter("name");
    }


    // 1.获取单个参数 ，通过url中 后面加 ? 参数来传递的
    @RequestMapping("/sayhi3")
//    public String say3(@RequestParam("username")  String name) {
    // 注意加上 RequestParam 的效果就是 重命名 和 设置前端是不是必须传递这个参数
    public String say3(@RequestParam("username")  String name) {
        return "hi spring mvc " + name;
    }

    @RequestMapping("/sayhi4")
    public String say4(Integer id) {  // Integer是包装类，是包装int的对象，是类型，默认都是null
        if(id == null) {
            return "没有传递参数";  //返回这个给前端，可以有回旋的余地，而不是直接报错，直接报错前端收不到
        }
        return "hi spring mvc " + id;
    }

    @RequestMapping("/sayhi5")
    public String say5(int id) {
        return "hi spring mvc " + id;  // 不传递默认会报错，不是0，假如是0的话，那传入的0和默认的0就没法区分了
                                       // 所以参数传递，不要使用基本数据类型，要使用对应的包装类
    }
}
